﻿#region License statement
// NJamb, a specification and delta-specification DSL
// Copyright (c) 2010-2011, Mark Knell
// Published under the MIT License; all other rights reserved
#endregion

#region using...
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using NJamb.NUnit;
using NJamb.Parser.SpecificationBuilders.SubjectHas.Simple.Enumerable.Quantifiers;
using NJamb.Parser.Subjects.Singular;
using NJamb.Specifications.Simple;
using NUnit.Framework;
#endregion

namespace NJamb.DemoCode.Schoolbuses
{
	public class Schoolbus
	{
		public const int RequiredFunctioningTires = 6;
		private readonly List<Tire> _tires;

		public Schoolbus()
		{
			_tires = Enumerable.Range(1, RequiredFunctioningTires).Select(x => new Tire()).ToList();
		}

		public ReadOnlyCollection<Tire> Tires
		{
			get { return new ReadOnlyCollection<Tire>(_tires); }
		}

		public bool CanTransportKids()
		{
			return _tires.Count(x => !x.Punctured) >= RequiredFunctioningTires;
		}
	}

	public class Tire
	{
		public bool Punctured { get; set; }
	}

	public class SchoolbusFixture : ExperimentOn<Schoolbus>
	{
		[Test]
		public void CanTransportKids()
		{
			Expecting(ThatTheCollection(x => x.Tires).Has.CountOf(Schoolbus.RequiredFunctioningTires).Always(),
				ThatTheCollection(x => x.Tires).Has.No.ItemsSatisfying(y => y.Punctured) //
					.AndLater.Has.AtLeast(2).ItemsSatisfying(y => y.Punctured),
				That(x => x.CanTransportKids()).WillChangeTo(false));

			Try(x => x.Tires.First().Punctured = true);
		}

		[Test]
		public void CanTransportKids_Alt()
		{
			Try(x => x.Tires.First().Punctured = true);

			Expecting(That(x => x.CanTransportKids()).WillChangeTo(false),
				That(x => x.Tires.Count()).Is.EqualTo(Schoolbus.RequiredFunctioningTires).Always(),
				That(x => x.Tires.Count(y => y.Punctured)).Is.EqualTo(0).AndLater.Is.EqualTo(2));
		}

		protected override Schoolbus TestSubjectFactory()
		{
			return new Schoolbus();
		}
	}
}
